package com.bluefish.bltuan.dao.impl;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.stereotype.Repository;

import com.bluefish.bltuan.dao.ShopDao;
import com.bluefish.bltuan.module.Category;
import com.bluefish.bltuan.module.shop.TuanGou;
import com.bluefish.bltuan.tools.DateUtils;
import com.bluefish.bltuan.util.PageIndex;

@Repository
public class ShopDaoImpl extends AbstractDaoImpl<TuanGou, Integer> implements ShopDao{

	/**
	 * 
	 */
	private static final long serialVersionUID = 2775470488856917908L;

	private static final String PUBLISHED_DATE = "publishedDate";
	
	private static final String EXPIRE_TIME = "expireTime";
	
	private static final String PUBLISHED = "published";

	protected static final String CITY = "city";

	protected static final String NICK = "nick";
	
	public List<TuanGou> list(Date date, boolean needPublished) {
		String currentDay = DateUtils.getDateString(date);
		if(needPublished)
			return this.listByPropertys(new String[]{PUBLISHED,PUBLISHED_DATE},
				new Object[]{true,currentDay});
		else
			return this.listByPropertys(new String[]{PUBLISHED_DATE},
					new Object[]{currentDay});
	}
	
	@SuppressWarnings("unchecked")
	public List<TuanGou> listBefore(final Date date, final boolean needPublished) {
		final String currentDay = DateUtils.getDateString(date);
		return this.getHibernateTemplate().executeFind(new HibernateCallback<List<TuanGou>>() {

			public List<TuanGou> doInHibernate(Session session)
					throws HibernateException, SQLException {
				Criteria criteria = session.createCriteria(TuanGou.class)
					.add(Restrictions.lt(EXPIRE_TIME, currentDay))
					.addOrder(Order.desc(PUBLISHED_DATE));
				if(needPublished)
					criteria.add(Restrictions.eq(PUBLISHED, true));
				return criteria.list();
			}
		});
	}
	
	@SuppressWarnings("unchecked")
	public List<TuanGou> listBefore(final Date date, final int size, final boolean needPublished) {
		final String currentDay = DateUtils.getDateString(date);
		return this.getHibernateTemplate().executeFind(new HibernateCallback<List<TuanGou>>() {

			public List<TuanGou> doInHibernate(Session session)
					throws HibernateException, SQLException {
				Criteria criteria = session.createCriteria(TuanGou.class)
					.add(Restrictions.lt(EXPIRE_TIME, currentDay))
					.addOrder(Order.desc(PUBLISHED_DATE))
					.setMaxResults(size);
				if(needPublished)
					criteria.add(Restrictions.eq(PUBLISHED, true));
				return criteria.list();
			}
		});
	}

	@SuppressWarnings("unchecked")
	public List<TuanGou> listBefore(final Date date, final PageIndex pageIndex, final boolean needPublished) {
		final String currentDay = DateUtils.getDateString(date);
		return this.getHibernateTemplate().executeFind(new HibernateCallback<List<TuanGou>>() {

			public List<TuanGou> doInHibernate(Session session)
					throws HibernateException, SQLException {
				Criteria criteria = session.createCriteria(TuanGou.class)
					.add(Restrictions.lt(EXPIRE_TIME, currentDay))
					.addOrder(Order.desc(PUBLISHED_DATE));
				if(needPublished)
					criteria.add(Restrictions.eq(PUBLISHED, true));
				criteria.setProjection(Projections.rowCount());
				int size = ((Number)criteria.uniqueResult()).intValue();
				pageIndex.setTotalRows(size);
				criteria.setProjection(null);
				criteria.setFirstResult(pageIndex.getStartRow())
					.setMaxResults(pageIndex.getPageSize());
				return criteria.list();
			}
		});
	}
	
	@SuppressWarnings("unchecked")
	public List<TuanGou> listBeforeByCity(final Date date, final PageIndex pageIndex,
			final Category city, final boolean needPublished) {
		final String currentDay = DateUtils.getDateString(date);
		return this.getHibernateTemplate().executeFind(new HibernateCallback<List<TuanGou>>() {

			public List<TuanGou> doInHibernate(Session session)
					throws HibernateException, SQLException {
				Criteria criteria = session.createCriteria(TuanGou.class)
					.add(Restrictions.eq(CITY, city))
					.add(Restrictions.lt(EXPIRE_TIME, currentDay))
					.addOrder(Order.desc(PUBLISHED_DATE));
				if(needPublished)
					criteria.add(Restrictions.eq(PUBLISHED, true));
				criteria.setProjection(Projections.rowCount());
				int size = ((Number)criteria.uniqueResult()).intValue();
				pageIndex.setTotalRows(size);
				criteria.setProjection(null);
				criteria.setFirstResult(pageIndex.getStartRow())
					.setMaxResults(pageIndex.getPageSize());
				return criteria.list();
			}
		});
	}

	@SuppressWarnings("unchecked")
	public List<TuanGou> listAfterByCity(final Date date, final PageIndex pageIndex,
			final Category city, final boolean needPublished) {
		final String currentDay = DateUtils.getDateString(date);
		return this.getHibernateTemplate().executeFind(new HibernateCallback<List<TuanGou>>() {

			public List<TuanGou> doInHibernate(Session session)
					throws HibernateException, SQLException {
				Criteria criteria = session.createCriteria(TuanGou.class)
					.add(Restrictions.gt(PUBLISHED_DATE, currentDay))
					.add(Restrictions.eq(CITY, city))
					.addOrder(Order.desc(PUBLISHED_DATE));
				if(needPublished)
					criteria.add(Restrictions.eq(PUBLISHED, true));
				criteria.setProjection(Projections.rowCount());
				int size = ((Number)criteria.uniqueResult()).intValue();
				pageIndex.setTotalRows(size);
				criteria.setProjection(null);
				criteria.setFirstResult(pageIndex.getStartRow())
					.setMaxResults(pageIndex.getPageSize());
				return criteria.list();
			}
		});
	}
	
	public List<TuanGou> listByCity(Date date, Category city, boolean needPublished) {
		String currentDay = DateUtils.getDateString(date);
		if(needPublished)
			return this.listByPropertys(new String[]{PUBLISHED,PUBLISHED_DATE, CITY},
				new Object[]{true,currentDay,city});
		else
			return this.listByPropertys(new String[]{PUBLISHED_DATE, CITY},
					new Object[]{currentDay,city});
	}
	
	@SuppressWarnings("unchecked")
	public List<TuanGou> listAtDateAndCity(final String currentDate, final Category city) {
		return this.getHibernateTemplate().executeFind(new HibernateCallback<List<TuanGou>>(){

			public List<TuanGou> doInHibernate(Session session)
					throws HibernateException, SQLException {
				Criteria criteria = session.createCriteria(TuanGou.class)
					.add(Restrictions.eq(CITY, city))
					.add(Restrictions.eq(PUBLISHED, true))
					.add(Restrictions.le(PUBLISHED_DATE, currentDate))
					.add(Restrictions.gt(EXPIRE_TIME, currentDate));
				return criteria.list();
			}
		});
	}
	
	@SuppressWarnings("unchecked")
	public List<TuanGou> listNotAfterByCity(final PageIndex pageIndex, final Date date,
			final Category city, final boolean needpublished) {
		final String publishedDate = DateUtils.getDateString(date);
		return this.getHibernateTemplate().executeFind(new HibernateCallback<List<TuanGou>>(){

			public List<TuanGou> doInHibernate(Session session)
					throws HibernateException, SQLException {
				Criteria criteria = session.createCriteria(TuanGou.class)
					.add(Restrictions.eq(CITY, city))
					.add(Restrictions.lt(PUBLISHED_DATE, publishedDate));
				if(needpublished)
					criteria.add(Restrictions.eq(PUBLISHED, true));
				criteria.setProjection(Projections.rowCount());
				int count = ((Number)criteria.uniqueResult()).intValue();
				pageIndex.setTotalRows(count);
				criteria.setProjection(null)
					.setFirstResult(pageIndex.getStartRow())
					.setMaxResults(pageIndex.getPageSize());
				return criteria.list();
			}
			
		});
	}
	
	@SuppressWarnings("unchecked")
	public List<TuanGou> listByNick(final String nick, final boolean needPublished) {
		return this.getHibernateTemplate().executeFind(new HibernateCallback<List<TuanGou>>(){

			public List<TuanGou> doInHibernate(Session session)
					throws HibernateException, SQLException {
				Criteria criteria = session.createCriteria(TuanGou.class);
				criteria.add(Restrictions.eq(NICK, nick));
				if(needPublished)
					criteria.add(Restrictions.eq(PUBLISHED, true));
				return criteria.list();
			}
		});
	}
}
